/* 
 * Created by linzheyan at 2013-1-17 
 * Copyright RayChi.com 
 */

package com.qnvip.sbd.mybatis.util;

import com.qnvip.sbd.mybatis.sqlprovider.SqlProviderHelper;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author linzheyan
 *
 * 2013-1-17
 */
public class UpdateMap {
	
	private int id;

	private String table;
	private List<Field> fields = new ArrayList<Field>();
	private List<Field> where = new ArrayList<Field>();
	private String equals = "=";

	/**
	 * @param table
	 */
	public UpdateMap(String table) {
		this.table = table;
	}
	
	public UpdateMap(Object obj) {
		
	}
	
	/**
	 * 
	 * @param table
	 * @param whereColumn  where条件，仅支持一对
	 * @param whereValue	where 条件值 
	 * @param fields  成对出现
	 * @return
	 */
	public static UpdateMap N(String table, String whereColumn, String whereValue, Object... fields) {
		UpdateMap updateMap = new UpdateMap(table);
		int fieldLength = fields.length;
		if (fieldLength < 2) return null;
		for (int i = 0, count = fieldLength / 2; i < count; i++) {
			updateMap.addField(String.valueOf(fields[i * 2]), String.valueOf(fields[i * 2 + 1]));
		}
		updateMap.addWhere(whereColumn, whereValue);
		return updateMap;
	}
	
	/**
	 * 根据ID查询
	 * @param table
	 * @param id
	 * @param fields  成对出现
	 * @return
	 */
	public static UpdateMap N(String table, int id, Object... fields) {
		UpdateMap updateMap = new UpdateMap(table);
		int fieldLength = fields.length;
		if (fieldLength < 2) return null;
		for (int i = 0, count = fieldLength / 2; i < count; i++) {
			updateMap.addField(String.valueOf(fields[i * 2]), String.valueOf(fields[i * 2 + 1]));
		}
		updateMap.addWhere("id", id);
		return updateMap;
	}
	
	/**
	 * 
	 * @param table
	 * @param fields  更新字段 成对出现
	 * @param wheres  where条件 成对出现
	 * @return
	 */
	public static UpdateMap N(String table, Object[] fields, Object[] wheres) {
		UpdateMap updateMap = new UpdateMap(table);
		int fieldLength = fields.length;
		int whereLength = wheres.length;
		if (fieldLength < 2 || whereLength < 2) return null;
		for (int i = 0, count = fieldLength / 2; i < count; i++) {
			updateMap.addField(String.valueOf(fields[i * 2]), String.valueOf(fields[i * 2 + 1]));
		}
		for (int i = 0, count = fieldLength / 2; i < count; i++) {
			updateMap.addWhere(String.valueOf(fields[i * 2]), String.valueOf(fields[i * 2 + 1]));
		}
		return updateMap;
	}
	
	/**
	 * 将entity转为updatemap
	 * 
	 * @param object
	 * @return
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 */
	public static UpdateMap N(Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		return UpdateMap.N(object, null);
	}
	
	/**
	 * 将entity的指定字段转为updatemap
	 * 
	 * @param object
	 * @param targetFields  逗号隔开的字段
	 * @return
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 */
	public static UpdateMap N(Object object, String targetFields) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		return UpdateMap.N(object, true, targetFields);
	}
	
	/**
	 * 
	 * 
	 * @param object
	 * @param fillNull true=将null转为空字符串或0
	 * @param targetFields
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static UpdateMap N(Object object, boolean fillNull, String targetFields) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		String table = SqlProviderHelper.getTable(object);
		UpdateMap updateMap = new UpdateMap(table);
		ObjectStruct objectStruct = new ObjectStruct(object);
		Map<String, Method> getMethods = objectStruct.getGetMethods();
		java.lang.reflect.Field[] fields = object.getClass().getDeclaredFields();
		for (java.lang.reflect.Field field : fields) {
			Method getMethod = getMethods.get(field.getName());
			if (getMethod != null) {
				Object obj = getMethod.invoke(object);
				String val = null;
				if (obj == null) {
					if (fillNull) {
						String type = field.getType().getName();
						if (type.equals("java.lang.Double") || type.equals("java.lang.Float") || type.equals("java.lang.Long") || type.equals("java.lang.Integer")) {
							val = "0";
						} else {
							val = StringUtils.EMPTY;
						}
					}
				} else {
					val = String.valueOf(obj);
				}
				if (StringUtils.isBlank(targetFields)) {
					updateMap.addField(field.getName(), val);
				} else {
					targetFields = "," + targetFields + ",";
					if (targetFields.indexOf("," + field.getName() + ",") >= 0) {
						updateMap.addField(field.getName(), val);
					}
				}
			}
		}
		return updateMap;
	}

	/**
	 * @param name
	 * @param value
	 */
	public UpdateMap addField(String name, String value) {
		fields.add(new Field(name, value, equals));
		return this;
	}

	/**
	 * @param name
	 * @param value
	 */
	public UpdateMap addField(String name, int value) {
		fields.add(new Field(name, String.valueOf(value), equals));
		return this;
	}
	
	public UpdateMap addField(String name, long value) {
		fields.add(new Field(name, String.valueOf(value), equals));
		return this;
	}
	
	/**
	 * 对应 0:false 1:true
	 * @param name
	 * @param value
	 */
	public UpdateMap addField(String name, boolean value) {
		fields.add(new Field(name, value ? "1" : "0", equals));
		return this;
	}

	public UpdateMap addField(String name, float value) {
		fields.add(new Field(name, String.valueOf(value), equals));
		return this;
	}
	
	public UpdateMap addField(String name, double value) {
		fields.add(new Field(name, String.valueOf(value), equals));
		return this;
	}
	
	/**
	 * 
	 * @param name
	 * @param value
	 * @param column  true=$$ false=##
	 */
	public UpdateMap addField(String name, String value, boolean column) {
		fields.add(new Field(name, value, equals, column));
		return this;
	}

	/**
	 * 
	 * @param name
	 * @param vlaue
	 * @param operator
	 * @param column
	 */
	public UpdateMap addField(String name, String value, String operator, boolean column) {
		fields.add(new Field(name, value, operator, column));
		return this;
	}

	/**
	 * @param name
	 * @param value
	 */
	public UpdateMap addWhere(String name, String value) {
		where.add(new Field(name, value, equals));
		return this;
	}

	/**
	 * @param name
	 * @param value
	 */
	public UpdateMap addWhere(String name, int value) {
		where.add(new Field(name, String.valueOf(value), equals));
		return this;
	}
	
	/**
	 * @param name
	 * @param value
	 */
	public UpdateMap addWhere(String name, Long value) {
		where.add(new Field(name, String.valueOf(value), equals));
		return this;
	}

	/**
	 * @param name
	 * @param value
	 * @param operator
	 */
	public UpdateMap addWhere(String name, String value, String operator) {
		where.add(new Field(name, value, operator));
		return this;
	}

	/**
	 * @param name
	 * @param value
	 * @param operator
	 */
	public UpdateMap addWhere(String name, int value, String operator) {
		where.add(new Field(name, String.valueOf(value), operator));
		return this;
	}
	
	/**
	 * @param name
	 * @param value
	 * @param operator
	 */
	public UpdateMap addWhere(String name, Long value, String operator) {
		where.add(new Field(name, String.valueOf(value), operator));
		return this;
	}

	/**
	 * 
	 * @param name
	 * @param value
	 * @param column  true=$$ false=##
	 */
	public UpdateMap addWhere(String name, String value, boolean column) {
		where.add(new Field(name, value, equals, column));
		return this;
	}

	/**
	 * 
	 * @param name
	 * @param vlaue
	 * @param operator
	 * @param column
	 */
	public UpdateMap addWhere(String name, String value, String operator, boolean column) {
		where.add(new Field(name, value, operator, column));
		return this;
	}

	public String getTable() {
		return table;
	}

	public void setTable(String table) {
		this.table = table;
	}

	public List<Field> getFields() {
		return fields;
	}

	public void setFields(List<Field> fields) {
		this.fields = fields;
	}

	public List<Field> getWhere() {
		return where;
	}

	public void setWhere(List<Field> where) {
		this.where = where;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
}
